Fixed a get/put_page mismatch for guest L2 pages. Sometimes, when you
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 8 Dec 2005 14:18:13 +0000 (15:18 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 8 Dec 2005 14:18:13 +0000 (15:18 +0100)
destroy an OS when it is in real mode, there is an extra put_page in
domain_relinquish_resource.  This causes the page be freed with
non-zero type count.  With ASSERT enabled, hypervisor will crash; with
debug=n, on some machines, the system will hang in
alloc_domheap_pages, due to type_info being a union with cpumask and
not equal to 0.

Signed-off-by: Xiaofeng Ling <xiaofeng.ling@intel.com>
xen/arch/x86/vmx.c

index e8e1c9f1e0d8fe21a77aae1544f0f53415216248..eb1252ff1ceb41db8ff3d231548d5b052ca18691 100644 (file)
@@ -905,7 +905,7 @@ vmx_world_save(struct vcpu *v, struct vmx_assist_context *c)
 int
 vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
 {
-    unsigned long mfn, old_cr4;
+    unsigned long mfn, old_cr4, old_base_mfn;
     int error = 0;
 
     error |= __vmwrite(GUEST_RIP, c->eip);
@@ -945,7 +945,12 @@ vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
             return 0;
         }
         mfn = get_mfn_from_pfn(c->cr3 >> PAGE_SHIFT);
+        if(!get_page(pfn_to_page(mfn), v->domain))
+                return 0;
+        old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
         v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
+        if (old_base_mfn)
+             put_page(pfn_to_page(old_base_mfn));
         update_pagetables(v);
         /*
          * arch.shadow_table should now hold the next CR3 for shadow
@@ -1174,9 +1179,11 @@ static int vmx_set_cr0(unsigned long value)
     }
 
     if(!((value & X86_CR0_PE) && (value & X86_CR0_PG)) && paging_enabled)
-        if(v->arch.arch_vmx.cpu_cr3)
+        if(v->arch.arch_vmx.cpu_cr3){
             put_page(pfn_to_page(get_mfn_from_pfn(
                       v->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT)));
+            v->arch.guest_table = mk_pagetable(0);
+        }
 
     /*
      * VMX does not implement real-mode virtualization. We emulate